// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: wsfuyibing <682805@qq.com>
// Date: 2025-04-02

package render

import (
	"fmt"
	"gitee.com/go-libs/runtime/util/table"
	"os"
	"strings"
)

type terminal struct {
	Length int
	Table  table.Table // 表格
	Width  map[int]int // 宽度
	Indent string      // 缩进
}

func (o *terminal) output(str string) {
	_, _ = fmt.Fprintf(os.Stdout, o.Indent+fmt.Sprintf("%c[%d;%d;%dm%s%c[0m", 0x1B, 0, 0, 33, str, 0x1B)+"\n")
}

func (o *terminal) print() {
	o.Width = o.Table.GetWidths()
	o.Length = len(o.Width)

	o.printTitle()
	o.printBegin()
	o.printHead()
	o.printSeparator()
	o.printBody()
	o.printEnd()
}

func (o *terminal) printBody() {
	if body := o.Table.GetBody(); body != nil {
		body.Iterate(func(_ int, row table.Row) {
			o.printRow(row)
		})
	}
}

func (o *terminal) printRow(row table.Row) {
	str := "│"

	for i := 0; i < len(o.Width); i++ {
		width := o.Width[i]
		format := fmt.Sprintf(` %%-%ds │`, width)

		if cell := row.GetCell(i); cell != nil {
			str += fmt.Sprintf(format, cell.String())
		} else {
			str += fmt.Sprintf(format, "")
		}
	}
	o.output(str)
}

func (o *terminal) printTitle() {
	if title := o.Table.GetTitle(); title != "" {
		o.output("▼ <" + title + ">")
	}
}

func (o *terminal) printHead() {
	if head := o.Table.GetHead(); head != nil {
		o.printRow(head.GetRow())
	}
}

func (o *terminal) printSeparator() {
	str := "├"
	for i := 0; i < o.Length; i++ {
		width := o.Width[i] + 2
		str += strings.Repeat("─", width)
		if i == (o.Length - 1) {
			str += "┤"
		} else {
			str += "┼"
		}
	}
	o.output(str)
}

func (o *terminal) printBegin() {
	str := "┌"
	for i := 0; i < o.Length; i++ {
		width := o.Width[i] + 2
		str += strings.Repeat("─", width)
		if i == (o.Length - 1) {
			str += "┐"
		} else {
			str += "┬"
		}
	}
	o.output(str)
}

func (o *terminal) printEnd() {
	str := "└"
	for i := 0; i < o.Length; i++ {
		width := o.Width[i] + 2
		str += strings.Repeat("─", width)
		if i == (o.Length - 1) {
			str += "┘"
		} else {
			str += "┴"
		}
	}
	o.output(str)
}

func Terminal(tbl table.Table, indents ...string) {
	o := &terminal{Table: tbl}

	if len(indents) > 0 && indents[0] != "" {
		o.Indent = indents[0]
	}

	o.print()
}
